#include "login.h"

#include <fstream>
#include <iostream>
#include <stdlib.h>

using namespace std;

Login::Login() {
    ler_utilizadores();

}

Login::~Login() {
    escrever_utilizadores();
}

void Login::escrever_utilizadores() {
    ofstream f_utilizadores("utilizadores.txt");

    for (vector<nomepass>::iterator k = utilizadores.begin(); k != utilizadores.end(); k++) {
        f_utilizadores << rot13(k->nome) << endl
                       << rot13(k->password) << endl
                       << k->nivel << endl;
    }

}

void Login::ler_utilizadores() {
    // /*
    //  * Se o vector utilizadores nao tiver tamanho 0, entao ja le-mos o ficheiro.
    //  * Deste modo, nao devemos de voltar a ler-lo, senao ficamos com nomes repetidos no vector.
    //  * PARANOIA :)
    //  */
    // if (utilizadores.size() != 0)
    //     throw VectorJaContemElementos();


    ifstream f_utilizadores("utilizadores.txt");

    // String usada para ler o ficheiro linha a linha
    string temp_linha_ficheiro;

    while (!f_utilizadores.eof()) {
        // Variavel a ser adicionada ao vector utilizadores
        nomepass temp_nome;

        getline(f_utilizadores, temp_linha_ficheiro);

        /*
         * A funcao escrever_utilizadores coloca um newline no fim do ficheiro.
         * Desta forma, se encontrar-mos um linha vazia, podemos usar isso como
         * uma condicao de paragem do ciclo.
         */
        if (temp_linha_ficheiro == "")
            break;

        temp_nome.nome = rot13(temp_linha_ficheiro);

        getline(f_utilizadores, temp_linha_ficheiro);
        temp_nome.password = rot13(temp_linha_ficheiro);

        getline(f_utilizadores, temp_linha_ficheiro);
        temp_nome.nivel = atoi(temp_linha_ficheiro.c_str());

        utilizadores.push_back(temp_nome);
    }
}

/*
 * Valores que a funcao pode devolver
 *  0 - Utilizador fez login com o nivel de administrador
 *  1 - Utilizador fez login com o nivel de utilizador
 * -1 - Utilizador nao fez login
 */
int Login::efectuar_login(string nome, string password) {
    for (vector<nomepass>::iterator k = utilizadores.begin(); k != utilizadores.end(); k++)
    {
        if (k->nome == nome)
            if (k->password == password) {
                if (k->nivel == 0)
                    return 0;   // Login administrador
                else
                    return 1;   // Login utilizador
            }
    }
    return -1; // Login nao foi feito com sucesso
}

bool Login::adicionar_novo_login(string nome, string password, int nivel)
{

    nomepass util_adicionar;

    util_adicionar.nome = nome;
    util_adicionar.password = password;
    util_adicionar.nivel = nivel;


    /*
     * Como uma das formas de se sair da funcao Login::menu() e inserindo o caracter 0,
     * nao podemos criar um utilizador com esse nome, senao ele nunca conseguiria fazer login
     */
    if (util_adicionar.nome == "0")
        return false;

    // Se o nome existir retorna false, senao, retorna true
    for (vector<nomepass>::size_type k = 0; k != utilizadores.size(); k++)
    {
        if (utilizadores[k].nome == util_adicionar.nome) {
            // Nao pode haver dois nome iguais
            return false;
        }
    }

    utilizadores.push_back(util_adicionar);

    return true;
}

string Login::rot13(string cadeia) {
    /*
     * Devolve a cadeia de caracteres modificada com o algoritmo rot13
     * Para mais informacoes ver: http://en.wikipedia.org/wiki/ROT13
     */

    string cadeia_rot13;

    for (string::size_type k = 0; k != cadeia.size(); k++) {
        if (cadeia[k] >= 'a' && cadeia[k] <= 'm')
            cadeia_rot13.push_back(cadeia[k] + 13);
        else if (cadeia[k] >= 'A' && cadeia[k] <= 'M') // Conservar as maiusculas
            cadeia_rot13.push_back(cadeia[k] + 13);
        /*
         * Se se somar 13 a letras a partir do caracter 'm', o caracter
         * obtido nao sera uma letra.
         * Felizmente, devido a natureza do algoritmo rot13, podemos
         * simplesmente substrair 13 a esses caracteres e obter o valor
         * correcto.
         */
        else if (cadeia[k] >= 'n' && cadeia[k] <= 'z')
            cadeia_rot13.push_back(cadeia[k] - 13);
        else if (cadeia[k] >= 'N' && cadeia[k] <= 'Z') // Conservar as maiusculas
            cadeia_rot13.push_back(cadeia[k] - 13);
        // Nao existe block else, porque nao modificamos os simbolos na cadeia
    }

    return cadeia_rot13;
}

